import pygame
import math

class Button:
    """按钮类，用于创建可点击的UI元素"""
    
    def __init__(self, x, y, width, height, text, color=(100, 100, 255), hover_color=(130, 130, 255), text_color=(255, 255, 255), font_size=28):
        """
        初始化按钮
        
        参数:
            x, y: 按钮左上角坐标
            width, height: 按钮宽高
            text: 按钮文本
            color: 按钮颜色
            hover_color: 鼠标悬停时的颜色
            text_color: 文本颜色
            font_size: 字体大小
        """
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.text_color = text_color
        self.font_size = font_size
        self.is_hovered = False
        self.font = pygame.font.SysFont('SimHei', font_size)
        
    def draw(self, screen):
        """
        绘制按钮
        
        参数:
            screen: pygame的Surface对象
        """
        # 创建渐变效果的按钮背景
        color = self.hover_color if self.is_hovered else self.color
        
        # 创建按钮主体surface，以支持渐变和透明度效果
        button_surface = pygame.Surface((self.rect.width, self.rect.height), pygame.SRCALPHA)
        
        # 定义渐变起始和结束颜色
        top_color = tuple(min(c + 30, 255) for c in color)
        bottom_color = tuple(max(c - 20, 0) for c in color)
        
        # 绘制渐变背景
        for y in range(self.rect.height):
            # 计算当前位置的颜色
            progress = y / self.rect.height
            current_color = tuple(
                int(top_color[i] * (1 - progress) + bottom_color[i] * progress)
                for i in range(3)
            )
            current_color = (*current_color, 230)  # 增加一点透明度
            
            # 绘制水平线条
            pygame.draw.line(
                button_surface,
                current_color,
                (0, y),
                (self.rect.width, y)
            )
        
        # 绘制圆角矩形边框
        pygame.draw.rect(
            button_surface, 
            (255, 255, 255, 100), 
            pygame.Rect(0, 0, self.rect.width, self.rect.height),
            border_radius=10
        )
        
        # 如果处于悬停状态，添加额外的发光效果
        if self.is_hovered:
            # 创建发光边缘
            glow_surf = pygame.Surface((self.rect.width + 10, self.rect.height + 10), pygame.SRCALPHA)
            pygame.draw.rect(
                glow_surf, 
                (*top_color, 100), 
                pygame.Rect(0, 0, self.rect.width + 10, self.rect.height + 10),
                border_radius=15
            )
            screen.blit(glow_surf, (self.rect.x - 5, self.rect.y - 5))
            
            # 创建内侧亮光
            highlight = pygame.Surface((self.rect.width - 20, self.rect.height - 20), pygame.SRCALPHA)
            pygame.draw.rect(
                highlight,
                (255, 255, 255, 50),
                pygame.Rect(0, 0, self.rect.width - 20, self.rect.height - 20),
                border_radius=5
            )
            button_surface.blit(highlight, (10, 10))
        
        # 将按钮主体绘制到屏幕
        screen.blit(button_surface, self.rect)
        
        # 绘制文本
        text_surf = self.font.render(self.text, True, self.text_color)
        text_rect = text_surf.get_rect(center=self.rect.center)
        
        # 如果悬停，使文本轻微上移，产生按压效果
        if self.is_hovered:
            text_rect.y -= 2
            
        screen.blit(text_surf, text_rect)
        
    def update(self, mouse_pos):
        """
        更新按钮状态
        
        参数:
            mouse_pos: 鼠标位置(x, y)
            
        返回值:
            bool: 鼠标是否悬停在按钮上
        """
        self.is_hovered = self.rect.collidepoint(mouse_pos)
        return self.is_hovered
        
    def is_clicked(self, mouse_pos, mouse_button):
        """
        检查按钮是否被点击
        
        参数:
            mouse_pos: 鼠标位置(x, y)
            mouse_button: 鼠标按键状态
            
        返回值:
            bool: 按钮是否被点击
        """
        return self.rect.collidepoint(mouse_pos) and mouse_button[0]

class Menu:
    """菜单基类"""
    
    def __init__(self, screen_width, screen_height):
        """
        初始化菜单
        
        参数:
            screen_width: 屏幕宽度
            screen_height: 屏幕高度
        """
        self.screen_width = screen_width
        self.screen_height = screen_height
        self.buttons = []
        
    def handle_event(self, event):
        """
        处理事件，由子类实现
        
        参数:
            event: pygame事件对象
            
        返回值:
            根据子类定义返回不同的值
        """
        pass
        
    def update(self, mouse_pos):
        """
        更新菜单状态
        
        参数:
            mouse_pos: 鼠标位置(x, y)
        """
        for button in self.buttons:
            button.update(mouse_pos)
            
    def draw(self, screen):
        """
        绘制菜单
        
        参数:
            screen: pygame的Surface对象
        """
        # 绘制背景
        screen.fill((30, 30, 40))
        
        # 绘制所有按钮
        for button in self.buttons:
            button.draw(screen)

class MainMenu(Menu):
    """主菜单类"""
    
    def __init__(self, screen_width, screen_height):
        """初始化主菜单"""
        super().__init__(screen_width, screen_height)
        
        # 创建标题
        self.title = "开心消消乐"
        self.title_font = pygame.font.SysFont('SimHei', 64)
        
        # 创建按钮
        button_width = 200
        button_height = 50
        button_y_start = screen_height // 2 - 50
        button_spacing = 70
        button_x = (screen_width - button_width) // 2
        
        self.buttons = [
            Button(button_x, button_y_start, button_width, button_height, "开始游戏", (50, 150, 50), (70, 180, 70)),
            Button(button_x, button_y_start + button_spacing, button_width, button_height, "排行榜", (50, 100, 150), (70, 120, 180)),
            Button(button_x, button_y_start + button_spacing * 2, button_width, button_height, "退出游戏", (150, 50, 50), (180, 70, 70))
        ]
        
    def handle_event(self, event):
        """
        处理菜单事件
        
        参数:
            event: pygame事件对象
            
        返回值:
            str: 'play', 'leaderboard', 'quit' 或 None
        """
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            mouse_pos = pygame.mouse.get_pos()
            
            if self.buttons[0].rect.collidepoint(mouse_pos):
                return 'play'
            elif self.buttons[1].rect.collidepoint(mouse_pos):
                return 'leaderboard'
            elif self.buttons[2].rect.collidepoint(mouse_pos):
                return 'quit'
                
        return None
        
    def draw(self, screen):
        """绘制主菜单"""
        # 绘制渐变背景
        for y in range(self.screen_height):
            # 从深蓝到紫色的渐变
            r = int(30 + (50 * y / self.screen_height))
            g = int(30 + (30 * y / self.screen_height))
            b = int(50 + (70 * y / self.screen_height))
            pygame.draw.line(screen, (r, g, b), (0, y), (self.screen_width, y))
            
        # 添加装饰性光效
        for i in range(20):  # 添加一些随机位置的光点
            x = int(pygame.time.get_ticks() / 50 + i * 100) % self.screen_width
            y = int(30 + (self.screen_height - 60) * i / 20)
            radius = 2 + int(3 * abs(pygame.math.Vector2(x, y).length() / 1000))
            alpha = 100 + int(155 * abs(math.sin(pygame.time.get_ticks() / 1000 + i / 3)))
            
            # 创建发光效果
            glow_surface = pygame.Surface((radius * 6, radius * 6), pygame.SRCALPHA)
            pygame.draw.circle(glow_surface, (200, 200, 255, alpha // 4), 
                              (radius * 3, radius * 3), radius * 3)
            pygame.draw.circle(glow_surface, (220, 220, 255, alpha // 2), 
                              (radius * 3, radius * 3), radius * 2)
            pygame.draw.circle(glow_surface, (255, 255, 255, alpha), 
                              (radius * 3, radius * 3), radius)
                              
            screen.blit(glow_surface, 
                      (x - radius * 3, y - radius * 3))
        
        # 绘制标题
        # 创建发光文本效果
        title_glow = pygame.font.SysFont('SimHei', 68)
        title_main = pygame.font.SysFont('SimHei', 64)
        glow_color = (100, 100, 255)
        main_color = (255, 255, 255)
        
        # 阴影/发光效果
        glow_surf = title_glow.render(self.title, True, glow_color)
        glow_rect = glow_surf.get_rect(center=(self.screen_width // 2, self.screen_height // 4))
        
        # 主文本
        title_surf = title_main.render(self.title, True, main_color)
        title_rect = title_surf.get_rect(center=(self.screen_width // 2, self.screen_height // 4))
        
        # 先绘制发光效果，再绘制主文本
        screen.blit(glow_surf, (glow_rect.x - 2, glow_rect.y - 2))
        screen.blit(title_surf, title_rect)
        
        # 绘制按钮
        for button in self.buttons:
            button.draw(screen)
            
        # 绘制版权信息
        font = pygame.font.SysFont('SimHei', 16)
        text = font.render("© 2024 开心消消乐", True, (200, 200, 200))
        text_rect = text.get_rect(center=(self.screen_width // 2, self.screen_height - 30))
        screen.blit(text, text_rect)

class LevelSelectMenu(Menu):
    """关卡选择菜单类"""
    
    def __init__(self, screen_width, screen_height, levels=None):
        """
        初始化关卡选择菜单
        
        参数:
            screen_width: 屏幕宽度
            screen_height: 屏幕高度
            levels: 关卡数据字典
        """
        super().__init__(screen_width, screen_height)
        
        self.title = "选择关卡"
        self.title_font = pygame.font.SysFont('SimHei', 48)
        self.back_button = Button(50, 50, 120, 40, "返回", (100, 100, 100), (130, 130, 130))
        
        # 创建关卡按钮
        self.level_buttons = []
        self.create_level_buttons(levels or {1: {}, 2: {}, 3: {}})
        
    def create_level_buttons(self, levels):
        """
        创建关卡按钮
        
        参数:
            levels: 关卡数据字典
        """
        button_size = 100
        button_spacing = 30
        max_buttons_per_row = 4
        
        # 计算起始位置，使按钮居中
        total_width = min(len(levels), max_buttons_per_row) * button_size + (min(len(levels), max_buttons_per_row) - 1) * button_spacing
        start_x = (self.screen_width - total_width) // 2
        start_y = self.screen_height // 3
        
        self.level_buttons = []
        
        for i, level_id in enumerate(sorted(levels.keys())):
            row = i // max_buttons_per_row
            col = i % max_buttons_per_row
            
            x = start_x + col * (button_size + button_spacing)
            y = start_y + row * (button_size + button_spacing)
            
            # 根据难度设置颜色
            difficulty = levels[level_id].get("difficulty", 1)
            color = (50, 150, 50)  # 简单 - 绿色
            if difficulty == 2:
                color = (150, 150, 50)  # 中等 - 黄色
            elif difficulty >= 3:
                color = (150, 50, 50)  # 困难 - 红色
                
            button = Button(x, y, button_size, button_size, f"关卡 {level_id}", color, 
                          (color[0] + 30, color[1] + 30, color[2] + 30))
            self.level_buttons.append((level_id, button))
        
    def handle_event(self, event):
        """
        处理菜单事件
        
        参数:
            event: pygame事件对象
            
        返回值:
            tuple: (str, int) - ('level', level_id), ('back', None) 或 (None, None)
        """
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            mouse_pos = pygame.mouse.get_pos()
            
            # 检查返回按钮
            if self.back_button.rect.collidepoint(mouse_pos):
                return ('back', None)
                
            # 检查关卡按钮
            for level_id, button in self.level_buttons:
                if button.rect.collidepoint(mouse_pos):
                    return ('level', level_id)
                    
        return (None, None)
        
    def update(self, mouse_pos):
        """更新菜单状态"""
        self.back_button.update(mouse_pos)
        for _, button in self.level_buttons:
            button.update(mouse_pos)
            
    def draw(self, screen):
        """绘制关卡选择菜单"""
        # 绘制背景
        screen.fill((30, 30, 50))
        
        # 绘制标题
        title_surf = self.title_font.render(self.title, True, (255, 255, 255))
        title_rect = title_surf.get_rect(center=(self.screen_width // 2, self.screen_height // 6))
        screen.blit(title_surf, title_rect)
        
        # 绘制返回按钮
        self.back_button.draw(screen)
        
        # 绘制关卡按钮
        for _, button in self.level_buttons:
            button.draw(screen)
            
class LeaderboardMenu(Menu):
    """排行榜菜单类"""
    
    def __init__(self, screen_width, screen_height):
        """初始化排行榜菜单"""
        super().__init__(screen_width, screen_height)
        
        self.title = "排行榜"
        self.title_font = pygame.font.SysFont('SimHei', 48)
        self.back_button = Button(50, 50, 120, 40, "返回", (100, 100, 100), (130, 130, 130))
        
        # 分页按钮
        self.prev_button = Button(screen_width // 4, screen_height - 70, 100, 40, "上一页", (100, 100, 100), (130, 130, 130))
        self.next_button = Button(screen_width * 3 // 4 - 100, screen_height - 70, 100, 40, "下一页", (100, 100, 100), (130, 130, 130))
        
        # 关卡筛选按钮
        self.level_filter_buttons = []
        self.create_level_filter_buttons()
        
        # 排行榜数据
        self.leaderboard_data = []
        self.current_level = None
        self.page = 0
        self.items_per_page = 10
        
    def create_level_filter_buttons(self):
        """创建关卡筛选按钮"""
        button_width = 80
        button_spacing = 10
        total_width = 4 * button_width + 3 * button_spacing
        start_x = (self.screen_width - total_width) // 2
        y = 120
        
        self.level_filter_buttons = [
            Button(start_x, y, button_width, 30, "全部", (70, 70, 130), (90, 90, 150)),
            Button(start_x + button_width + button_spacing, y, button_width, 30, "关卡1", (70, 130, 70), (90, 150, 90)),
            Button(start_x + 2 * (button_width + button_spacing), y, button_width, 30, "关卡2", (130, 130, 70), (150, 150, 90)),
            Button(start_x + 3 * (button_width + button_spacing), y, button_width, 30, "关卡3", (130, 70, 70), (150, 90, 90))
        ]
        
    def set_leaderboard_data(self, data):
        """
        设置排行榜数据
        
        参数:
            data: 排行榜数据列表
        """
        self.leaderboard_data = data
        self.page = 0
        
    def handle_event(self, event):
        """
        处理菜单事件
        
        参数:
            event: pygame事件对象
            
        返回值:
            tuple: (str, int) - ('back', None), ('filter', level_id), ('page', direction) 或 (None, None)
        """
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            mouse_pos = pygame.mouse.get_pos()
            
            # 检查返回按钮
            if self.back_button.rect.collidepoint(mouse_pos):
                return ('back', None)
                
            # 检查分页按钮
            if self.prev_button.rect.collidepoint(mouse_pos):
                return ('page', -1)
            elif self.next_button.rect.collidepoint(mouse_pos):
                return ('page', 1)
                
            # 检查关卡筛选按钮
            for i, button in enumerate(self.level_filter_buttons):
                if button.rect.collidepoint(mouse_pos):
                    level_id = None if i == 0 else i
                    return ('filter', level_id)
                    
        return (None, None)
        
    def update(self, mouse_pos):
        """更新菜单状态"""
        self.back_button.update(mouse_pos)
        self.prev_button.update(mouse_pos)
        self.next_button.update(mouse_pos)
        
        for button in self.level_filter_buttons:
            button.update(mouse_pos)
            
    def change_page(self, direction):
        """
        改变页码
        
        参数:
            direction: 页码改变方向，1表示下一页，-1表示上一页
        """
        max_page = max(0, (len(self.leaderboard_data) - 1) // self.items_per_page)
        self.page = max(0, min(self.page + direction, max_page))
        
    def draw(self, screen):
        """绘制排行榜菜单"""
        # 绘制背景
        screen.fill((30, 30, 50))
        
        # 绘制标题
        title_surf = self.title_font.render(self.title, True, (255, 255, 255))
        title_rect = title_surf.get_rect(center=(self.screen_width // 2, 60))
        screen.blit(title_surf, title_rect)
        
        # 绘制返回按钮
        self.back_button.draw(screen)
        
        # 绘制关卡筛选按钮
        for i, button in enumerate(self.level_filter_buttons):
            # 高亮显示当前选中的筛选按钮
            level_id = None if i == 0 else i
            if level_id == self.current_level:
                pygame.draw.rect(screen, (255, 255, 255), button.rect, 3, border_radius=10)
            button.draw(screen)
            
        # 绘制排行榜数据
        self.draw_leaderboard_data(screen)
        
        # 绘制分页按钮
        if self.page > 0:
            self.prev_button.draw(screen)
        if (self.page + 1) * self.items_per_page < len(self.leaderboard_data):
            self.next_button.draw(screen)
            
    def draw_leaderboard_data(self, screen):
        """绘制排行榜数据"""
        if not self.leaderboard_data:
            # 绘制无数据提示
            font = pygame.font.SysFont('SimHei', 32)
            text = font.render("暂无排行数据", True, (200, 200, 200))
            text_rect = text.get_rect(center=(self.screen_width // 2, self.screen_height // 2))
            screen.blit(text, text_rect)
            return
            
        # 计算本页显示的数据
        start = self.page * self.items_per_page
        end = min(start + self.items_per_page, len(self.leaderboard_data))
        
        # 设置表头
        header_y = 180
        font = pygame.font.SysFont('SimHei', 24)
        
        headers = ["排名", "玩家", "关卡", "分数", "时间"]
        widths = [80, 200, 80, 100, 200]
        
        total_width = sum(widths)
        start_x = (self.screen_width - total_width) // 2
        
        # 绘制表头
        pygame.draw.line(screen, (150, 150, 150), (start_x, header_y), (start_x + total_width, header_y), 2)
        
        x = start_x
        for i, header in enumerate(headers):
            text = font.render(header, True, (200, 200, 200))
            text_rect = text.get_rect(midtop=(x + widths[i] // 2, header_y - 30))
            screen.blit(text, text_rect)
            x += widths[i]
            
        # 绘制数据行
        row_height = 40
        font = pygame.font.SysFont('SimHei', 20)
        
        for i in range(start, end):
            data = self.leaderboard_data[i]
            row_y = header_y + (i - start + 1) * row_height
            
            # 交替行背景色
            if (i - start) % 2 == 0:
                pygame.draw.rect(screen, (40, 40, 60), (start_x, row_y, total_width, row_height))
            else:
                pygame.draw.rect(screen, (50, 50, 70), (start_x, row_y, total_width, row_height))
                
            # 绘制排名
            rank_text = font.render(f"{i + 1}", True, (255, 255, 255))
            rank_rect = rank_text.get_rect(center=(start_x + widths[0] // 2, row_y + row_height // 2))
            screen.blit(rank_text, rank_rect)
            
            # 绘制玩家名
            name_text = font.render(data.get('username', '未知'), True, (255, 255, 255))
            name_rect = name_text.get_rect(midleft=(start_x + widths[0] + 10, row_y + row_height // 2))
            screen.blit(name_text, name_rect)
            
            # 绘制关卡
            level_text = font.render(f"{data.get('level_id', 0)}", True, (255, 255, 255))
            level_rect = level_text.get_rect(center=(start_x + widths[0] + widths[1] + widths[2] // 2, row_y + row_height // 2))
            screen.blit(level_text, level_rect)
            
            # 绘制分数
            score_text = font.render(f"{data.get('score', 0)}", True, (255, 255, 255))
            score_rect = score_text.get_rect(midright=(start_x + widths[0] + widths[1] + widths[2] + widths[3] - 10, row_y + row_height // 2))
            screen.blit(score_text, score_rect)
            
            # 绘制时间
            played_at = data.get('played_at', '')
            if isinstance(played_at, str) and played_at:
                played_at = played_at[:19]  # 截取日期时间部分
            time_text = font.render(f"{played_at}", True, (200, 200, 200))
            time_rect = time_text.get_rect(midleft=(start_x + widths[0] + widths[1] + widths[2] + widths[3] + 10, row_y + row_height // 2))
            screen.blit(time_text, time_rect)
            
        # 绘制页码信息
        if self.leaderboard_data:
            page_info = f"第 {self.page + 1} 页，共 {(len(self.leaderboard_data) - 1) // self.items_per_page + 1} 页"
            page_text = font.render(page_info, True, (150, 150, 150))
            page_rect = page_text.get_rect(center=(self.screen_width // 2, self.screen_height - 40))
            screen.blit(page_text, page_rect) 